# -*- coding: utf-8 -*-
"""
巡检应用定义表 t_patrol_app_def 的 6 个接口（字符型默认值改为空串）
"""
from datetime import datetime
from flask import request
from flask_jwt_extended import jwt_required
from flask_restx import Namespace, Resource, fields
from sqlalchemy import or_

from app1 import db
from app1.models import PatrolAppDef

ns_app_def = Namespace('ns_app_def', description='巡检应用定义')

# ========================== 模型定义 ==========================
model_item = ns_app_def.model('PatrolAppDefItem', {
    'id': fields.Integer(required=True, description='主键'),
    'app_name': fields.String(required=True, description='应用中文名'),
    'app_name_short': fields.String(required=True, description='英文简称'),
    'patrol_name': fields.Raw(description='巡检配置名，存储巡检配置属组'),
    'app_type': fields.Integer(required=True, description='1业务 2中间件 3数据库 4基础设施'),
    'require_manual_patrol': fields.Boolean(required=True, description='是否人工巡检'),
    'patrol_frequency': fields.String(description='DAILY/WEEKLY/MONTHLY'),
    'manual_patrol_cycle': fields.Integer(description='人工巡检周期(天)'),
    'responsible_person': fields.String(description='负责人域账号'),
    'responsible_team': fields.String(description='负责团队'),
    'contact_info': fields.String(description='电话/邮箱/企微群'),
    'app_status': fields.Boolean(required=True, description='0停用 1启用'),
    'config_params': fields.Raw(description='JSON 扩展'),
    'remark': fields.String(description='备注'),
    'create_time': fields.String(description='创建时间'),
    'update_time': fields.String(description='更新时间')
})

model_resp = ns_app_def.model('PatrolAppDefResp', {
    'message': fields.Nested(ns_app_def.model('Msg', {
        'result': fields.Integer(description='0=成功 1=失败'),
        'result_text': fields.String,
        'count': fields.Integer,
        'data': fields.List(fields.Nested(model_item))
    }))
})

# ---------- 新增 ----------
model_add = ns_app_def.model('PatrolAppDefAdd', {
    'app_name': fields.String(required=True, description='应用中文名', default=''),
    'app_name_short': fields.String(required=True, description='英文简称（唯一）', default=''),
    'patrol_name': fields.Raw(description='巡检配置名，存储巡检配置属组'),
    'app_type': fields.Integer(required=True, description='1业务 2中间件 3数据库 4基础设施'),
    'require_manual_patrol': fields.Boolean(required=True, default=False),
    'patrol_frequency': fields.String(description='DAILY/WEEKLY/MONTHLY', default=''),
    'manual_patrol_cycle': fields.Integer(description='人工巡检周期(天)'),
    'responsible_person': fields.String(description='负责人域账号', default=''),
    'responsible_team': fields.String(description='负责团队', default=''),
    'contact_info': fields.String(description='电话/邮箱/企微群', default=''),
    'app_status': fields.Boolean(required=True, default=True),
    'config_params': fields.Raw(description='JSON 扩展'),
    'remark': fields.String(description='备注', default='')
})

# ---------- 更新 ----------
model_upd = ns_app_def.model('PatrolAppDefUpd', {
    'app_name_short': fields.String(required=True, description='应用英文简称（定位用，不更新）', default=''),
    'app_name': fields.String(description='应用中文名', default=''),
    'patrol_name': fields.Raw(description='巡检配置名，存储巡检配置属组'),
    'app_type': fields.Integer(description='1业务 2中间件 3数据库 4基础设施'),
    'require_manual_patrol': fields.Boolean(description='是否人工巡检'),
    'patrol_frequency': fields.String(description='DAILY/WEEKLY/MONTHLY', default=''),
    'manual_patrol_cycle': fields.Integer(description='人工巡检周期(天)'),
    'responsible_person': fields.String(description='负责人域账号', default=''),
    'responsible_team': fields.String(description='负责团队', default=''),
    'contact_info': fields.String(description='电话/邮箱/企微群', default=''),
    'app_status': fields.Boolean(description='0停用 1启用'),
    'config_params': fields.Raw(description='JSON 扩展'),
    'remark': fields.String(description='备注', default='')
})

# ---------- 主键短名 ----------
model_short = ns_app_def.model('PatrolAppDefShort', {
    'app_name_short': fields.String(required=True, description='应用英文简称', default='')
})

# ---------- 分页+条件 ----------
model_page = ns_app_def.model('PatrolAppDefPage', {
    'page': fields.Integer(default=1, description='页码'),
    'size': fields.Integer(default=20, description='每页条数'),
    'app_name': fields.String(default='', description='应用中文名（模糊，空忽略）'),
    'app_name_short': fields.String(default='', description='英文简称（模糊，空忽略）'),
    'patrol_name': fields.String(default='', description='巡检配置名（模糊，空忽略）'),
    'app_type': fields.Integer(default=0, description='1业务 2中间件 3数据库 4基础设施（0忽略）'),
    'require_manual_patrol': fields.Boolean(default=None, description='是否人工巡检（None忽略）')
})


# ---------- 多值查询模型 ----------
# 多值删除模型
model_mult_del = ns_app_def.model('PatrolAppDefMultDel', {
    'app_name_shorts': fields.List(fields.String, required=True, description='英文简称列表', default=[])
})

# 多值查询模型
model_mult_get = ns_app_def.model('PatrolAppDefMultGet', {
    'app_name_shorts': fields.List(fields.String, required=True, description='英文简称列表', default=[])
})

# 多值分页查询模型
model_mult_page = ns_app_def.model('PatrolAppDefMultPage', {
    'page': fields.Integer(default=1, description='页码'),
    'size': fields.Integer(default=20, description='每页条数'),
    'app_names': fields.List(fields.String, description='应用中文名列表（多值）', default=[]),
    'app_name_shorts': fields.List(fields.String, description='英文简称列表（多值）', default=[]),
    'app_type': fields.Integer(default=0, description='1业务 2中间件 3数据库 4基础设施（0忽略）'),
    'require_manual_patrol': fields.Boolean(default=None, description='是否人工巡检（None忽略）')
})

# ========================== 接口实现 ==========================

@ns_app_def.route('/add')
class AddResource(Resource):
    # @jwt_required()
    @ns_app_def.expect(model_add)
    @ns_app_def.marshal_with(model_resp)
    def post(self):
        data = request.get_json()

        # 1. 去空格后非空校验
        app_name = data.get('app_name', '').strip()
        app_name_short = data.get('app_name_short', '').strip()
        if not app_name or not app_name_short:
            return {
                'message': {
                    'result': 1,
                    'result_text': 'app_name 和 app_name_short 不能为空',
                    'count': 0,
                    'data': []
                }
            }, 400

        # 2. 唯一性校验
        if PatrolAppDef.query.filter_by(app_name_short=app_name_short).first():
            return {
                'message': {
                    'result': 1,
                    'result_text': 'app_name_short 已存在',
                    'count': 0,
                    'data': []
                }
            }, 400

        # 3. 处理 patrol_name 字段（如果是字符串，尝试解析为 JSON）
        patrol_name = data.get('patrol_name')
        if isinstance(patrol_name, str) and patrol_name.strip():
            try:
                import json
                data['patrol_name'] = json.loads(patrol_name)
            except:
                # 如果解析失败，保持原样
                pass

        # 4. 落地
        row = PatrolAppDef(**data)
        try:
            db.session.add(row)
            db.session.commit()
            return {
                'message': {
                    'result': 0,
                    'result_text': '新增成功',
                    'count': 1,
                    'data': [row.to_dict()]
                }
            }, 201
        except Exception as e:
            db.session.rollback()
            return {
                'message': {
                    'result': 1,
                    'result_text': f'新增失败: {e}',
                    'count': 0,
                    'data': []
                }
            }, 500


@ns_app_def.route('/delete')
class DeleteResource(Resource):
    # @jwt_required()
    @ns_app_def.expect(model_short)
    @ns_app_def.marshal_with(model_resp)
    def post(self):
        short = request.get_json()['app_name_short']
        row = PatrolAppDef.query.filter_by(app_name_short=short).first()
        if not row:
            return {'message': {'result': 1, 'result_text': '记录不存在', 'count': 0, 'data': []}}, 404
        try:
            db.session.delete(row)
            db.session.commit()
            return {'message': {'result': 0, 'result_text': '删除成功', 'count': 1, 'data': [row.to_dict()]}}
        except Exception as e:
            db.session.rollback()
            return {'message': {'result': 1, 'result_text': f'删除失败: {e}', 'count': 0, 'data': []}}, 500


@ns_app_def.route('/update')
class UpdateResource(Resource):
    # @jwt_required()
    @ns_app_def.expect(model_upd)
    @ns_app_def.marshal_with(model_resp)
    def post(self):
        data = request.get_json()

        # 1. 取出定位键
        short = data.pop('app_name_short', '').strip()
        if not short:
            return {'message': {'result': 1, 'result_text': 'app_name_short（定位键）不能为空', 'count': 0, 'data': []}}, 404

        # 2. 再剔除所有不允许更新的字段（保险）
        immutable = ['id', 'create_time', 'update_time']
        for f in immutable:
            data.pop(f, None)

        # 3. 业务非空校验示例
        if 'app_name' in data and not data['app_name'].strip():
            return {'message': {'result': 1, 'result_text': 'app_name 不能为空', 'count': 0, 'data': []}}, 400

        # 4. 处理 patrol_name 字段（如果是字符串，尝试解析为 JSON）
        patrol_name = data.get('patrol_name')
        if isinstance(patrol_name, str) and patrol_name.strip():
            try:
                import json
                data['patrol_name'] = json.loads(patrol_name)
            except:
                # 如果解析失败，保持原样
                pass

        row = PatrolAppDef.query.filter_by(app_name_short=short).first()
        if not row:
            return {'message': {'result': 1, 'result_text': '记录不存在', 'count': 0, 'data': []}}, 404

        # 5. 赋值（此时 data 里已没有 app_name_short）
        for k, v in data.items():
            setattr(row, k, v)
        row.update_time = datetime.utcnow()

        try:
            db.session.commit()
            return {'message': {'result': 0, 'result_text': '更新成功', 'count': 1, 'data': [row.to_dict()]}}
        except Exception as e:
            db.session.rollback()
            return {'message': {'result': 1, 'result_text': f'更新失败: {e}', 'count': 0, 'data': []}}, 500


@ns_app_def.route('/get')
class GetResource(Resource):
    # @jwt_required()
    @ns_app_def.expect(model_short)
    @ns_app_def.marshal_with(model_resp)
    def post(self):
        short = request.get_json()['app_name_short']
        row = PatrolAppDef.query.filter_by(app_name_short=short).first()
        if not row:
            return {'message': {'result': 1, 'result_text': '记录不存在', 'count': 0, 'data': []}}, 404
        return {'message': {'result': 0, 'result_text': '查询成功', 'count': 1, 'data': [row.to_dict()]}}


@ns_app_def.route('/list')
class ListResource(Resource):
    # @jwt_required()
    @ns_app_def.marshal_with(model_resp)
    def get(self):
        rows = PatrolAppDef.query.all()
        return {'message': {'result': 0, 'result_text': '查询成功', 'count': len(rows),
                            'data': [r.to_dict() for r in rows]}}


@ns_app_def.route('/page')
class PageResource(Resource):
    # @jwt_required()
    @ns_app_def.expect(model_page)
    @ns_app_def.marshal_with(model_resp)
    def post(self):
        data = request.get_json()
        page = max(1, data.get('page', 1))
        size = max(1, data.get('size', 20))

        query = PatrolAppDef.query

        if data.get('app_name'):
            query = query.filter(PatrolAppDef.app_name.contains(data['app_name']))
        if data.get('app_name_short'):
            query = query.filter(PatrolAppDef.app_name_short.contains(data['app_name_short']))
        if data.get('patrol_name'):
            # 由于 patrol_name 是 JSON 字段，使用 JSON_CONTAINS 进行查询
            query = query.filter(PatrolAppDef.patrol_name.contains(data['patrol_name']))
        if data.get('app_type'):
            query = query.filter_by(app_type=data['app_type'])
        if data.get('require_manual_patrol') is not None:
            query = query.filter_by(require_manual_patrol=data['require_manual_patrol'])

        total = query.count()
        rows = query.limit(size).offset((page - 1) * size).all()

        return {
            'message': {
                'result': 0,
                'result_text': '查询成功',
                'count': total,
                'data': [r.to_dict() for r in rows]
            }
        }


# ========================== 新增多值查询接口 ==========================

@ns_app_def.route('/deletemult')
class DeleteMultResource(Resource):
    # @jwt_required()
    @ns_app_def.expect(model_mult_del)
    @ns_app_def.marshal_with(model_resp)
    def post(self):
        """批量删除 - 根据英文简称列表删除多条记录"""
        data = request.get_json()
        app_name_shorts = data.get('app_name_shorts', [])

        if not app_name_shorts:
            return {
                'message': {
                    'result': 1,
                    'result_text': 'app_name_shorts 不能为空',
                    'count': 0,
                    'data': []
                }
            }, 400

        # 查询所有匹配的记录
        rows = PatrolAppDef.query.filter(PatrolAppDef.app_name_short.in_(app_name_shorts)).all()

        if not rows:
            return {
                'message': {
                    'result': 1,
                    'result_text': '未找到匹配的记录',
                    'count': 0,
                    'data': []
                }
            }, 404

        deleted_data = []
        try:
            for row in rows:
                deleted_data.append(row.to_dict())
                db.session.delete(row)
            db.session.commit()

            return {
                'message': {
                    'result': 0,
                    'result_text': f'批量删除成功，共删除 {len(rows)} 条记录',
                    'count': len(rows),
                    'data': deleted_data
                }
            }
        except Exception as e:
            db.session.rollback()
            return {
                'message': {
                    'result': 1,
                    'result_text': f'批量删除失败: {e}',
                    'count': 0,
                    'data': []
                }
            }, 500


@ns_app_def.route('/getmult')
class GetMultResource(Resource):
    # @jwt_required()
    @ns_app_def.expect(model_mult_get)
    @ns_app_def.marshal_with(model_resp)
    def post(self):
        """批量查询 - 根据英文简称列表查询多条记录"""
        data = request.get_json()
        app_name_shorts = data.get('app_name_shorts', [])

        if not app_name_shorts:
            return {
                'message': {
                    'result': 1,
                    'result_text': 'app_name_shorts 不能为空',
                    'count': 0,
                    'data': []
                }
            }, 400

        # 查询所有匹配的记录
        rows = PatrolAppDef.query.filter(PatrolAppDef.app_name_short.in_(app_name_shorts)).all()

        return {
            'message': {
                'result': 0,
                'result_text': f'查询成功，共找到 {len(rows)} 条记录',
                'count': len(rows),
                'data': [r.to_dict() for r in rows]
            }
        }


@ns_app_def.route('/pagemult')
class PageMultResource(Resource):
    # @jwt_required()
    @ns_app_def.expect(model_mult_page)
    @ns_app_def.marshal_with(model_resp)
    def post(self):
        """多值分页查询 - 支持应用名和英文简称的多值查询"""
        data = request.get_json()
        page = max(1, data.get('page', 1))
        size = max(1, data.get('size', 20))

        query = PatrolAppDef.query

        # 多值条件过滤
        app_names = data.get('app_names', [])
        app_name_shorts = data.get('app_name_shorts', [])

        # 构建多值查询条件
        conditions = []

        if app_names:
            conditions.append(PatrolAppDef.app_name.in_(app_names))

        if app_name_shorts:
            conditions.append(PatrolAppDef.app_name_short.in_(app_name_shorts))

        # 如果有多个条件，使用 OR 连接
        if conditions:
            query = query.filter(or_(*conditions))

        # 其他单值条件
        if data.get('app_type'):
            query = query.filter_by(app_type=data['app_type'])
        if data.get('require_manual_patrol') is not None:
            query = query.filter_by(require_manual_patrol=data['require_manual_patrol'])

        total = query.count()
        rows = query.limit(size).offset((page - 1) * size).all()

        return {
            'message': {
                'result': 0,
                'result_text': '多值查询成功',
                'count': total,
                'data': [r.to_dict() for r in rows]
            }
        }
